package com.gaff.emp.core.util;

import cn.hutool.core.util.StrUtil;
import com.gaff.emp.core.modules.auth.LoginUserInfo;
import com.gaff.emp.core.modules.auth.interceptor.AuthorizationInterceptor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.Objects;

@Slf4j
@Component
public class ContextUtil implements ApplicationContextAware {

    public static ApplicationContext applicationContext;

    private static String rootPath;

    private static String globalEncoding;

    @SneakyThrows
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        ContextUtil.applicationContext = applicationContext;
        rootPath = applicationContext.getEnvironment().getProperty("project.home");
        if (StrUtil.isBlank(rootPath)) {
            rootPath = System.getProperty("user.dir");
        }
        globalEncoding = System.getProperty("file.encoding");
        log.info("EMP Root Path : " + rootPath);
        log.info("EMP Global Encoding : " + globalEncoding);
    }

    public static String getRootPath() {
        return rootPath;
    }

    public static String getStaticPath(){
        return rootPath + File.separator + "static" + File.separator;
    }

    public static String getGlobalEncoding() {
        return globalEncoding;
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static Object getBean(Class clazz) {
        return applicationContext.getBean(clazz);
    }

    public static <T> T getBean(String name, Class<T> requiredType) {
        return applicationContext.getBean(name, requiredType);
    }

    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }

    public static void download(String contentType, byte[] bytes) throws IOException {
        download(contentType, Identities.uid(), bytes);
    }

    public static void download(String contentType, String fileName, byte[] bytes) throws IOException {
        HttpServletResponse response = getHttpServletResponse();
        response.setContentType(contentType);
        response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);

        ServletOutputStream out = response.getOutputStream();
        out.write(bytes);
        out.flush();
        IOUtils.closeQuietly(out);
    }

    public static HttpServletRequest getHttpServletRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        return request;
    }

    public static HttpServletResponse getHttpServletResponse() {
        HttpServletResponse response = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        return response;
    }

    public static LoginUserInfo getCurrentUserInfo() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (servletRequestAttributes == null) {
            return null;
        }
        HttpServletRequest request = servletRequestAttributes.getRequest();
        if (request == null) {
            return null;
        }
        return (LoginUserInfo) request.getAttribute(AuthorizationInterceptor.USER_INFO_KEY);
    }

}
